using System;
using System.Globalization;
using DocumentFormat.OpenXml.Spreadsheet;

namespace ExcelTemplateEngine.OpenXML
{
    /// <summary>
    /// 基于OpenXML的单元格实现
    /// </summary>
    public class OpenXMLCell : ICell
    {
        private readonly Cell _cell;
        private readonly OpenXMLWorksheet _worksheet;
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="cell">OpenXML单元格对象</param>
        /// <param name="worksheet">所属工作表</param>
        public OpenXMLCell(Cell cell, OpenXMLWorksheet worksheet)
        {
            _cell = cell ?? throw new ArgumentNullException(nameof(cell));
            _worksheet = worksheet ?? throw new ArgumentNullException(nameof(worksheet));
        }
        
        /// <summary>
        /// 单元格地址（如"A1"）
        /// </summary>
        public string Address => _cell.CellReference?.Value ?? string.Empty;
        
        /// <summary>
        /// 行号（1-based）
        /// </summary>
        public int Row
        {
            get
            {
                if (string.IsNullOrEmpty(Address))
                    return 0;
                var (row, _) = CellAddressHelper.ParseAddress(Address);
                return row;
            }
        }
        
        /// <summary>
        /// 列号（1-based）
        /// </summary>
        public int Column
        {
            get
            {
                if (string.IsNullOrEmpty(Address))
                    return 0;
                var (_, column) = CellAddressHelper.ParseAddress(Address);
                return column;
            }
        }
        
        /// <summary>
        /// 单元格值
        /// </summary>
        public object Value
        {
            get => GetValue();
            set => SetValue(value);
        }
        
        /// <summary>
        /// 公式
        /// </summary>
        public string Formula
        {
            get => _cell.CellFormula?.Text ?? string.Empty;
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    _cell.CellFormula = null;
                }
                else
                {
                    _cell.CellFormula = new CellFormula(value);
                }
            }
        }
        
        /// <summary>
        /// 样式ID
        /// </summary>
        public uint? StyleIndex
        {
            get => _cell.StyleIndex?.Value;
            set => _cell.StyleIndex = value;
        }
        
        /// <summary>
        /// 数据类型
        /// </summary>
        public CellDataType DataType
        {
            get => ConvertCellType(_cell.DataType?.Value);
            set => _cell.DataType = ConvertToOpenXmlType(value);
        }
        
        /// <summary>
        /// 获取格式化后的文本
        /// </summary>
        /// <returns>格式化的文本</returns>
        public string GetFormattedValue()
        {
            var value = GetValue();
            if (value == null)
                return string.Empty;
                
            // 简化的格式化实现
            switch (value)
            {
                case DateTime dateValue:
                    return dateValue.ToString("yyyy-MM-dd");
                case double doubleValue:
                    return doubleValue.ToString("G", CultureInfo.InvariantCulture);
                case decimal decimalValue:
                    return decimalValue.ToString("G", CultureInfo.InvariantCulture);
                case bool boolValue:
                    return boolValue ? "TRUE" : "FALSE";
                default:
                    return value.ToString() ?? string.Empty;
            }
        }
        
        /// <summary>
        /// 获取单元格值
        /// </summary>
        /// <returns>单元格值</returns>
        private object GetValue()
        {
            if (_cell.CellValue == null || string.IsNullOrEmpty(_cell.CellValue.Text))
                return string.Empty;
                
            var value = _cell.CellValue.Text;
            
            if (_cell.DataType != null && _cell.DataType.Value == CellValues.SharedString)
            {
                // 从共享字符串表获取
                if (int.TryParse(value, out int index))
                {
                    return _worksheet.Workbook.SharedStrings.GetString(index);
                }
            }
            else if (_cell.DataType != null && _cell.DataType.Value == CellValues.Boolean)
            {
                return value == "1";
            }
            else if (_cell.DataType == null || _cell.DataType.Value == CellValues.Number)
            {
                if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out double number))
                {
                    // 检查是否是日期（简化检测）
                    if (IsDateValue(number))
                    {
                        return DateTime.FromOADate(number);
                    }
                    return number;
                }
            }
            
            return value;
        }
        
        /// <summary>
        /// 设置单元格值
        /// </summary>
        /// <param name="value">要设置的值</param>
        private void SetValue(object value)
        {
            if (value == null)
            {
                _cell.CellValue = null;
                _cell.DataType = null;
                return;
            }
            
            switch (value)
            {
                case string stringValue:
                    SetStringValue(stringValue);
                    break;
                    
                case double doubleValue:
                    SetNumberValue(doubleValue);
                    break;
                    
                case float floatValue:
                    SetNumberValue(floatValue);
                    break;
                    
                case decimal decimalValue:
                    SetNumberValue((double)decimalValue);
                    break;
                    
                case int intValue:
                    SetNumberValue(intValue);
                    break;
                    
                case long longValue:
                    SetNumberValue(longValue);
                    break;
                    
                case bool boolValue:
                    SetBooleanValue(boolValue);
                    break;
                    
                case DateTime dateValue:
                    SetDateValue(dateValue);
                    break;
                    
                default:
                    // 其他类型转换为字符串
                    SetStringValue(value.ToString() ?? string.Empty);
                    break;
            }
        }
        
        /// <summary>
        /// 设置字符串值
        /// </summary>
        /// <param name="value">字符串值</param>
        private void SetStringValue(string value)
        {
            var index = _worksheet.Workbook.SharedStrings.AddString(value);
            _cell.CellValue = new CellValue(index.ToString());
            _cell.DataType = CellValues.SharedString;
        }
        
        /// <summary>
        /// 设置数字值
        /// </summary>
        /// <param name="value">数字值</param>
        private void SetNumberValue(double value)
        {
            _cell.CellValue = new CellValue(value.ToString(CultureInfo.InvariantCulture));
            _cell.DataType = CellValues.Number;
        }
        
        /// <summary>
        /// 设置布尔值
        /// </summary>
        /// <param name="value">布尔值</param>
        private void SetBooleanValue(bool value)
        {
            _cell.CellValue = new CellValue(value ? "1" : "0");
            _cell.DataType = CellValues.Boolean;
        }
        
        /// <summary>
        /// 设置日期值
        /// </summary>
        /// <param name="value">日期值</param>
        private void SetDateValue(DateTime value)
        {
            // Excel stores dates as numbers (OLE Automation date)
            var oaDate = value.ToOADate();
            _cell.CellValue = new CellValue(oaDate.ToString(CultureInfo.InvariantCulture));
            _cell.DataType = CellValues.Number;
            // 注意：这里应该设置日期格式的样式，暂时简化处理
        }
        
        /// <summary>
        /// 检查数字是否是日期值
        /// </summary>
        /// <param name="value">数字值</param>
        /// <returns>是否是日期</returns>
        private bool IsDateValue(double value)
        {
            // 简化的日期检测：Excel的日期范围大约是 1900-01-01 到 9999-12-31
            // 对应的OA日期大约是 1 到 2958466
            return value >= 1 && value <= 2958466 && Math.Abs(value - Math.Round(value)) < 0.0001;
        }
        
        /// <summary>
        /// 转换OpenXML单元格类型为自定义类型
        /// </summary>
        /// <param name="cellValues">OpenXML单元格类型</param>
        /// <returns>自定义单元格类型</returns>
        private static CellDataType ConvertCellType(CellValues? cellValues)
        {
            if (!cellValues.HasValue)
                return CellDataType.Number;
                
            switch (cellValues.Value)
            {
                case CellValues.SharedString:
                    return CellDataType.SharedString;
                case CellValues.String:
                    return CellDataType.String;
                case CellValues.Boolean:
                    return CellDataType.Boolean;
                case CellValues.Number:
                    return CellDataType.Number;
                case CellValues.Error:
                    return CellDataType.Error;
                default:
                    return CellDataType.Number;
            }
        }
        
        /// <summary>
        /// 转换自定义类型为OpenXML单元格类型
        /// </summary>
        /// <param name="dataType">自定义单元格类型</param>
        /// <returns>OpenXML单元格类型</returns>
        private static CellValues ConvertToOpenXmlType(CellDataType dataType)
        {
            switch (dataType)
            {
                case CellDataType.SharedString:
                    return CellValues.SharedString;
                case CellDataType.String:
                    return CellValues.String;
                case CellDataType.Boolean:
                    return CellValues.Boolean;
                case CellDataType.Number:
                case CellDataType.Date:
                    return CellValues.Number;
                case CellDataType.Error:
                    return CellValues.Error;
                default:
                    return CellValues.Number;
            }
        }
    }
}